package pl.edu.pb.wi.cookbook.controller;

import java.util.Arrays;
import java.util.logging.Logger;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import pl.edu.pb.wi.cookbook.entity.Category;
import pl.edu.pb.wi.cookbook.form.NewCategoryForm;
import pl.edu.pb.wi.cookbook.form.RemoveCategoryForm;
import pl.edu.pb.wi.cookbook.service.CategoryService;

import com.googlecode.objectify.Key;

@Controller
@RequestMapping("/admin/category")
public class AdminCategoryController {
    private static final Logger log = Logger
            .getLogger(AdminCategoryController.class.getName());

    private CategoryService categoryService;

    @Autowired
    public AdminCategoryController(CategoryService categoryService) {
        this.categoryService = categoryService;
    }

    @RequestMapping(value = "create", method = RequestMethod.GET)
    public String create(Model model) {
        model.addAttribute("form", new NewCategoryForm());

        return "admin/category/create";
    }

    @RequestMapping(value = "create", method = RequestMethod.POST)
    public String create(@ModelAttribute("form")
    @Valid
    NewCategoryForm form, BindingResult results, Model model) {
        String returnPath = "admin/category/create";

        if (results.hasErrors()) {
            return returnPath;
        }

        try {
            Key<Category> parentCategoryKey = null;
            if (form.getParentCategoryId() > 0
                    && categoryService.isCategoryInDatabase(form
                            .getParentCategoryId())) {
                parentCategoryKey = new Key<Category>(Category.class,
                        form.getParentCategoryId());
            }

            categoryService.createCategory(form.getName(),
                    form.getDescription(), form.getCanAddRecipes(),
                    parentCategoryKey);

            model.addAttribute(
                    "successMsgs",
                    Arrays.asList(new String[] { String
                            .format("Kategoria '%s' została dodana do drzewa kategorii.",
                                    form.getName()) }));
        } catch (Exception e) {
            log.info(String.format(
                    "Problem with new category form. Exception: %s",
                    e.getMessage()));

            model.addAttribute(
                    "errorMsgs",
                    Arrays.asList(new String[] { "Wystąpił błąd. Spróbuj ponownie." }));

            returnPath = "message";
        }

        return returnPath;
    }

    @RequestMapping(value = "remove", method = RequestMethod.GET)
    public String remove(Model model) {
        model.addAttribute("form", new RemoveCategoryForm());

        return "admin/category/remove";
    }

    @RequestMapping(value = "remove", method = RequestMethod.POST)
    public String remove(@ModelAttribute("form")
    @Valid
    RemoveCategoryForm form, BindingResult results, Model model) {
        String returnPath = "admin/category/remove";

        if (results.hasErrors()) {
            return returnPath;
        }

        try {
            Category cat = categoryService.getCategory(form.getCategoryId());
            if (cat != null) {
                categoryService.remove(cat);

                model.addAttribute(
                        "successMsgs",
                        Arrays.asList(new String[] { String
                                .format("Kategoria '%s' została usunięta z drzewa kategorii.",
                                        cat.getName()) }));
            } else {
                model.addAttribute(
                        "errorMsgs",
                        Arrays.asList(new String[] { "Wybrano nieprawidłową kategorię." }));
            }
        } catch (Exception e) {
            log.info(String.format(
                    "Problem with new category form. Exception: %s",
                    e.getMessage()));

            model.addAttribute(
                    "errorMsgs",
                    Arrays.asList(new String[] { "Wystąpił błąd. Spróbuj ponownie." }));

            returnPath = "message";
        }

        return returnPath;
    }

    @RequestMapping("edit/{catId}")
    public String edit(@PathVariable("catId")
    Long catId, Model model) {
        if (catId == null || !categoryService.isCategoryInDatabase(catId)) {
            model.addAttribute("errorMsgs", Arrays
                    .asList(new String[] { "Nie istnieje taka kategoria." }));

            return "message";
        }

        Category cat = categoryService.getCategory(catId);
        NewCategoryForm form = new NewCategoryForm();
        form.setParentCategoryId(cat.getParentCategory() != null ? cat
                .getParentCategory().getId() : null);
        form.setName(cat.getName());
        form.setDescription(cat.getDescription());
        form.setCanAddRecipes(cat.getIsCanAddRecipes());

        model.addAttribute("form", form);
        model.addAttribute("id", catId);

        return "admin/category/edit";
    }

    @RequestMapping(value = "edit/{catId}", method = RequestMethod.POST)
    public String edit(@PathVariable("catId")
    Long catId, @ModelAttribute("form")
    @Valid
    NewCategoryForm form, BindingResult results, Model model) {
        String returnPath = "admin/category/edit";

        if (results.hasErrors()) {
            return returnPath;
        }

        try {
            Category cat = categoryService.getCategory(catId);
            if (cat != null) {
                Key<Category> parent = form.getParentCategoryId() == null ? null
                        : new Key<Category>(Category.class,
                                form.getParentCategoryId());

                if (parent != null && parent.getId() > 0
                        && categoryService.isCategoryInDatabase(parent.getId())) {
                    cat.setParentCategory(parent);
                } else {
                    cat.setParentCategory(null);
                }

                cat.setCanAddRecipes(form.getCanAddRecipes());
                cat.setName(form.getName());
                cat.setDescription(form.getDescription());

                categoryService.updateCategory(cat);

                model.addAttribute("successMsgs", Arrays
                        .asList(new String[] { String.format(
                                "Zmiany w kategorii '%s' zostały zapisane.",
                                form.getName()) }));

                returnPath = String.format("forward:/recipe/list/%d", catId);
            } else {
                model.addAttribute(
                        "errorMsgs",
                        Arrays.asList(new String[] { "Nie istnieje taka kategoria." }));

                return "message";
            }
        } catch (Exception e) {
            log.info(String.format(
                    "Problem with new category form. Exception: %s",
                    e.getMessage()));

            model.addAttribute(
                    "errorMsgs",
                    Arrays.asList(new String[] { "Wystąpił błąd. Spróbuj ponownie." }));

            returnPath = "message";
        }

        return returnPath;
    }
}
